package com.lark.web.service.impl;

import java.io.*;
import java.nio.channels.Channels;
import java.nio.channels.WritableByteChannel;
import java.sql.Date;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import com.github.dockerjava.api.command.InspectImageResponse;
import com.github.dockerjava.api.command.RemoveImageCmd;
import com.github.dockerjava.api.command.SaveImageCmd;
import com.github.dockerjava.core.DockerClientBuilder;
import com.lark.common.core.page.PageDomain;
import com.lark.common.utils.StringUtils;
import com.lark.common.utils.json.JSONObject;
import com.lark.common.utils.sql.SqlUtil;
import com.lark.web.docker.service.DockerUtil;
import com.lark.web.service.HostService;
import com.github.dockerjava.api.DockerClient;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.github.pagehelper.PageInfo;
import com.lark.common.core.domain.BaseEntity;
import com.lark.common.core.service.BaseServiceImpl;
import com.lark.web.mapper.ImageMapper;
import com.lark.web.domain.Image;
import com.lark.web.service.ImageService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;

import javax.servlet.http.HttpServletResponse;

/**
 * 镜像Service业务层处理
 * @author fei
 * @email 952597665@qq.com
 * @date 2024-08-11
 */
@Service
public class ImageServiceImpl extends BaseServiceImpl<ImageMapper, Image> implements ImageService {

    private static final Logger log = LoggerFactory.getLogger(ImageServiceImpl.class);

    private static  final String serverUrl="";

    @Autowired
    private HostService hostService;

    /**
     * 获取单条数据
     * @param image 镜像
     * @return 镜像
     */
    @Override
    public Image get(Image image) {
        Image dto = super.get(image);
        return dto;
    }

    /**
     * 获取单条数据
     * @param id 镜像id
     * @return 镜像
     */
    @Override
    public Image get(String id) {
        Image dto = super.get(id);
        return dto;
    }

    /**
     * 查询镜像列表
     * @param image 镜像
     * @return 镜像
     */
    @Override
    public List<Image> findList(Image image) {
		List<Image> imageList = super.findList(image);
        return imageList;
    }

    /**
     * 分页查询镜像列表
     * @param image 镜像
     * @return 镜像
     */
    @Override
    public PageInfo<Image> findPage(Image image) {

        DockerClient dockerClient = hostService.buildClient(image.getIp());
        List<Image> images = new ArrayList<Image>();


        List<com.github.dockerjava.api.model.Image> imageList=dockerClient.listImagesCmd().exec();
        imageList.forEach(ig -> {
            Image mg = new Image();
            mg.setImageId(StringUtils.substring(ig.getId(), 7, 19));
            if (Objects.nonNull(ig.getRepoTags()) && ig.getRepoTags().length > 0) {
                if(ig.getRepoTags()[0]!=null&&ig.getRepoTags()[0].length()>0){
                    String[] split = ig.getRepoTags()[0].split(":");
                    if(split.length>0) {
                    	mg.setImageRepository(split[0]);
                    	mg.setImageTag(split[1]);
                    }
                }

            }
            mg.setImageSize(String.valueOf(ig.getSize() / 1000 / 1000)); // M
            mg.setImageCreateTime(Date.from(Instant.ofEpochSecond(ig.getCreated())));
            images.add(mg);
        });

        PageDomain page = image.getPage();
        Integer pageNum = page.getPageNum();
        Integer pageSize = page.getPageSize();
        if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize)) {
            String orderBy = SqlUtil.escapeOrderBySql(page.getOrderBy());
            Boolean reasonable = page.getReasonable();
            PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable);
        }
        return new PageInfo(images);
    }


    /**
     * 保存镜像
     * @param image
     * @return 结果
     */
    @Override
    public boolean save(Image image) {
        return super.save(image);
    }

    /**
     * 删除镜像信息
     * @param image
     * @return 结果
     */
    @Override
    public boolean remove(Image image) {
        boolean result=true;
        String imageIdToDelete=image.getImageId();
        DockerClient dockerClient= DockerClientBuilder.getInstance("tcp://"+image.getIp()+":2375").build();
        RemoveImageCmd removeImageCmd = dockerClient.removeImageCmd(imageIdToDelete);
        removeImageCmd.exec();
        return result;
    }

    /**
     * 批量删除镜像
     * @param ids 需要删除的镜像ID
     * @return 结果
     */
    @Transactional(readOnly = false)
    @Override
    public int deleteImageByIds(String[] ids) {
        return mapper.deleteImageByIds(ids, BaseEntity.DEL_FLAG_DELETE);
    }

    /**
     * 启动镜像
     * @param imageName
     * @return
     */
    @Override
    public boolean startImage(Image image) {

        String imageName=image.getImageTag();
        String mServerUrl="tcp://"+image.getIp()+":2375";
        DockerClient dockerClient= DockerClientBuilder.getInstance(mServerUrl).build();


        // 创建容器
        String containerId = dockerClient.createContainerCmd(imageName)
                .exec()
                .getId();

        // 启动容器
        dockerClient.startContainerCmd(containerId).exec();
        return true;
    }

    @Override
    public InspectImageResponse viewImage(Image image) {
        String imageId=image.getImageId();
        String mServerUrl="tcp://"+image.getIp()+":2375";
        DockerClient dockerClient= DockerClientBuilder.getInstance(mServerUrl).build();

        InspectImageResponse response = dockerClient.inspectImageCmd(imageId).exec();
        System.out.println("Image Details:");
        System.out.println("Architecture: " + response.getArch());
        System.out.println("Author: " + response.getAuthor());
        System.out.println("Comment: " + response.getComment());
        System.out.println("Container: " + response.getContainer());
        System.out.println("ContainerConfig: " + response.getContainerConfig());
        System.out.println("Created: " + response.getCreated());
        System.out.println("Id: " + response.getId());
        System.out.println("Parent: " + response.getParent());
//        System.out.println("Path: " + response.get());
        System.out.println("Size: " + response.getSize());
        System.out.println("VirtualSize: " + response.getVirtualSize());
        return response;
    }

    @Override
    public ResponseEntity<StreamingResponseBody> exportImage(Image image, HttpServletResponse response) throws IOException {
        String imageName=image.getImageTag();
        String mServerUrl="tcp://"+image.getIp()+":2375";
        DockerClient dockerClient= DockerClientBuilder.getInstance(mServerUrl).build();
        try {

            // 执行保存镜像命令
            SaveImageCmd saveImageCmd = dockerClient.saveImageCmd(imageName);
            InputStream inputStream = saveImageCmd.exec();

            // 返回 StreamingResponseBody
            StreamingResponseBody responseBody = new StreamingResponseBody() {
                @Override
                public void writeTo(OutputStream outputStream) throws IOException {
                    byte[] buffer = new byte[1024*1024];
                    int length;
                    try {
                        while ((length = inputStream.read(buffer)) != -1) {
                            outputStream.write(buffer, 0, length);
                        }
                    } catch (IOException e) {
                        throw new RuntimeException("Error writing to output stream", e);
                    } finally {
                        try {
                            inputStream.close();
                        } catch (IOException e) {
                        }
                    }
                }
            };

            // 设置响应头
            HttpHeaders headers = new HttpHeaders();
            headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + imageName + ".tar\"");

            // 返回响应实体
            return ResponseEntity.ok()
                    .headers(headers)
                    .contentType(MediaType.APPLICATION_OCTET_STREAM)
                    .body(responseBody);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
        } finally {
            dockerClient.close();
        }

    }

}
